package def;


import def.Parser.ParseException;
import Basics.*;

public class Camera implements IAllSceneObjects{



	private my3DPoint eye;
	private myVector direction = null;
	private my3DPoint look_at = null;
	private myVector up_direction;
	private myVector right_direction;
	private double screen_dist;
	private double screen_width = 2.0;
	

	public my3DPoint getEye() {
		return eye;
	}



	public void setEye(my3DPoint eye) {
		this.eye = eye;
	}



	public myVector getDircetion() {
		return direction;
	}



	public void setDircetion(myVector dircetion) {
		this.direction = dircetion;
	}



	public my3DPoint getLook_at() {
		return look_at;
	}



	public void setLook_at(my3DPoint look_at) {
		this.look_at = look_at;
	}



	public myVector getUp_diraction() {
		return up_direction;
	}



	public void setUp_diraction(myVector up_diraction) {
		this.up_direction = up_diraction;
	}



	public double getScreen_dist() {
		return screen_dist;
	}



	public void setScreen_dist(double screen_dist) {
		this.screen_dist = screen_dist;
	}



	public double getScreen_width() {
		return screen_width;
	}



	public void setScreen_width(double screen_width) {
		this.screen_width = screen_width;
	}

	
	@Override
	public boolean setParameter(String name, String[] args) throws ParseException {
		int numOfArgs = args.length;
		switch(name) {
		
		case "eye":
			if (numOfArgs!=3) return false;
			this.eye = new my3DPoint(ourParser.parseArrayOfDoubles(args)); 
			return true;
		case "diraction":
			if (numOfArgs!=3) return false;
			this.direction = new myVector(ourParser.parseArrayOfDoubles(args));
			return true;
		case "look-at":
			if (numOfArgs!=3) return false;
			this.look_at = new my3DPoint(ourParser.parseArrayOfDoubles(args));
			return true;
		case "up-diraction":
			if (numOfArgs!=3) return false;
			this.up_direction = new myVector(ourParser.parseArrayOfDoubles(args));
			return true;
		case "screen-dist":
			if (numOfArgs!=1) return false;
			this.screen_dist = Double.parseDouble(args[0]);
			return true;
		case "screen-width":
			if (numOfArgs!=1) return false;
			this.screen_width = Double.parseDouble(args[0]);
			return true;
		default: return false;
		
		}
		
		
	}
	
	public my3DPoint getScreenPoint(double x, double y, double canvasWidth, double canvasHeight) {

        my3DPoint screenPoint;

        double factorWidth = screen_width / canvasWidth;
        double upDistanceFromCenter = (y - (canvasHeight / 2)) * factorWidth * -1;
        double rightDistanceFromCenter = (x - (canvasWidth / 2)) * factorWidth;

        screenPoint = eye.addToPoint(up_direction.ScaleVector(upDistanceFromCenter));
        screenPoint = screenPoint.addToPoint(right_direction.ScaleVector(rightDistanceFromCenter));

        return screenPoint;
    }
	
	   public boolean confirmObjectConditions() {

	        //if (upDirection == null || eye == null || screenDist <= 0) {
	         //   return false;
	        //}

	        //if (direction == null) {
	         //   if (lookAt == null) {
	          //      return false;
	           // } else {
	            //    direction = new Vector(eye, lookAt);
	            //}
	        //}
		   
		   if (this.direction!=null && this.look_at!=null) return false;
		   else if (this.look_at!=null) {
			   //set the direction according to the look at param
			   this.direction = new myVector((my3DPoint)this.eye, (my3DPoint)this.look_at);
		   }

	       // direction = direction.normalize();

	        // calculates the real up direction
	       // upDirection = upDirection.normalize();
	       // rightDirection = upDirection.crossProduct(direction);
		   
		  //case diraction and up direction are collinear
		   if (this.direction.isCollinearTo(up_direction)) return false; 
		   
		   //Get the real orthogonal value
		   myVector rightDirection = new myVector();
		   rightDirection = this.direction.crossProduct(this.up_direction);
		   //rightDirection.normalize();
		   this.up_direction = rightDirection.crossProduct(this.direction);

	        //// calculates the screen center
	        //screenCenter = eye.addVector(direction.scale(screenDist));

	        return true;
	    }
	
	
	
}
